
using Sustainalytics.ESG.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;



namespace Sustainalytics.CRT.Synchronization.Tests
{


    public class FocusedRatingsPeerListCompuationTests
    {
        private readonly List<RPCorporateScore> _input;
        private readonly FocusedRatingsIndustryListManager _sut;

        public FocusedRatingsPeerListCompuationTests()
        {
            this._input = new List<RPCorporateScore>
                              {
                                  new RPCorporateScore { CompanyId = Guid.NewGuid(), CompanyName = "test1", Rank = 1, Score = 90 },
                                  new RPCorporateScore { CompanyId = Guid.NewGuid(), CompanyName = "test1", Rank = 2, Score = 80 },
                                  new RPCorporateScore { CompanyId = Guid.NewGuid(), CompanyName = "test1", Rank = 3, Score = 70 },
                                  new RPCorporateScore { CompanyId = Guid.NewGuid(), CompanyName = "test1", Rank = 4, Score = 60 },
                                  new RPCorporateScore { CompanyId = Guid.NewGuid(), CompanyName = "test1", Rank = 5, Score = 50 },
                              };
            this._sut = new FocusedRatingsIndustryListManager(this._input);
        }

        [Fact]
        public void Given_A_Company_Peers_Will_List_All_Ranks_Will_Be_From_1_To_5()
        {
            var score = new RPCompanyESGComputationResult() { Id = new Guid(), OverallPerformance = new RPPerformance() { Score = 100 } };
            var list = this._sut.GetIndustryPeersForCompany(score, "companyMock");
            var actual = list.Select(x => x.Rank);
            Assert.Equal(Enumerable.Range(1, 5), actual);
        }

        [Fact]
        public void Given_A_Company_With_A_Score_Equal_To_Peer_Then_Ranks_Will_Be_Equal()
        {
            var score = new RPCompanyESGComputationResult { Id = new Guid(), OverallPerformance = new RPPerformance() { Score = 90 } };
            var actual = this._sut.GetIndustryPeersForCompany(score, "companyMock");

            Assert.Equal(actual[0].Rank, actual[1].Rank);
        }

        [Fact]
        public void Given_A_Company_With_A_Score_Equal_To_Peer_Then_The_Following_Ranks_Will_Be_Greater()
        {
            var score = new RPCompanyESGComputationResult { Id = new Guid(), OverallPerformance = new RPPerformance() { Score = 90 } };
            var actual = this._sut.GetIndustryPeersForCompany(score, "companyMock");

            var expected = actual.Count(x => x.Score >= score.OverallPerformance.Score);
            Assert.Equal(expected, actual[expected].Rank);
        }

        [Fact]
        public void Given_A_Company_With_Score_Higher_Than_Any_Industry_Peers_Will_Be_In_List()
        {
            var score = new RPCompanyESGComputationResult() { Id = new Guid(), OverallPerformance = new RPPerformance() { Score = 100 } };
            var actual = this._sut.GetIndustryPeersForCompany(score, "companyMock");
            var expected = new RPCorporateScore { CompanyId = score.Id, Score = score.OverallPerformance.Score, CompanyName = "companyMock", Rank = 1 };
            Assert.Contains(expected, actual);
        }

        [Fact]
        public void Given_A_Company_With_Score_Lower_Than_Any_Industry_Peer_Will_Not_Be_In_List()
        {
            var score = new RPCompanyESGComputationResult() { Id = new Guid(), OverallPerformance = new RPPerformance() { Score = 40 } };
            var actual = this._sut.GetIndustryPeersForCompany(score, "companyMock");

            Assert.Equal(this._input, actual);
        }

        [Fact]
        public void Given_A_List_Of_5_Peers_Should_Return_At_Most_5()
        {
            var score = new RPCompanyESGComputationResult() { Id = new Guid(), OverallPerformance = new RPPerformance() { Score = 80 } };
            var actual = this._sut.GetIndustryPeersForCompany(score, "companyMock");

            Assert.Equal(5, actual.Length);
        }
    }
}